package com.juyu.miliao.api.dao.redis;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

import com.juyu.miliao.api.dao.redis.usercache.UserCacheVo;
import com.juyu.miliao.api.dao.redis.usercache.UserInfoCache;
import com.juyu.miliao.api.handler.IntegralRewardsAndPunishmentsHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Repository;

import com.juyu.miliao.api.domain.Follow;
import com.juyu.miliao.api.util.RedisKeys;

import javax.annotation.Resource;

/**
 * @author pengs
 */
@Repository
public class FollowRedisDao {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserInfoCache userInfoCache;

    @Autowired
    private IntegralRewardsAndPunishmentsHandler integralRewardsAndPunishmentsHandler;

    public Map<Integer, String> getFollowIdsById(long id, int startNum, int pageSize) {
        // //我关注的
        // Set<String> userIds =
        // stringRedisTemplate.opsForZSet().reverseRange(RedisKeys.ZSET_FOLLOWTO.getValue(id),
        // startNum, startNum + pageSize-1);
        // return userIds.stream().map(s ->
        // Integer.parseInt(s)).collect(toList());
        Set<TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet()
                .reverseRangeWithScores(RedisKeys.ZSET_FOLLOWTO.getValue(id), startNum, startNum + pageSize - 1);
        Iterator<TypedTuple<String>> iterator = tuples.iterator();
        Map<Integer, String> map = new LinkedHashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        while (iterator.hasNext()) {
            TypedTuple<String> typedTuple = iterator.next();
            String s = typedTuple.getScore().toString();
            Double d = new Double(s);
            date.setTime(d.longValue());
            map.put(Integer.parseInt(typedTuple.getValue()), sdf.format(date));
        }
        return map;
    }

    public Boolean insertFollow(Follow entity) {
        long epochMilli = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Boolean add = false;
        add = stringRedisTemplate.opsForZSet().add(RedisKeys.ZSET_FOLLOWTO.getValue(entity.getUserId()),
                String.valueOf(entity.getFollowUserId()), epochMilli);

        add = stringRedisTemplate.opsForZSet().add(RedisKeys.ZSET_FOLLOWFROM.getValue(entity.getFollowUserId()),
                String.valueOf(entity.getUserId()), epochMilli);


        //用户去关注主播
        UserCacheVo followUserInfo = userInfoCache.getUserCacheInfo(entity.getFollowUserId());
        UserCacheVo userCacheVo = userInfoCache.getUserCacheInfo(entity.getUserId());

        if (followUserInfo.getIsHost() == 1&&userCacheVo.getIsHost()!=1) {

            add = stringRedisTemplate.opsForZSet().add(RedisKeys.ZSET_HOST_FOLLOWTO.getValue(entity.getUserId()),
                    String.valueOf(entity.getFollowUserId()), epochMilli);

            add = stringRedisTemplate.opsForZSet().add(RedisKeys.ZSET_HOST_FOLLOWFROM.getValue(entity.getFollowUserId()),
                    String.valueOf(entity.getUserId()), epochMilli);

            integralRewardsAndPunishmentsHandler.fansAddBy100(followUserInfo.getUserId());

        }else if(followUserInfo.getIsHost()!=1&&userCacheVo.getIsHost()==1){
            add = stringRedisTemplate.opsForZSet().add(RedisKeys.ZSET_HOST_FOLLOWTO.getValue(entity.getUserId()),
                    String.valueOf(entity.getFollowUserId()), epochMilli);
            add =stringRedisTemplate.opsForZSet().add(RedisKeys.ZSET_HOST_FOLLOWFROM.getValue(entity.getFollowUserId()),
                    String.valueOf(entity.getUserId()), epochMilli);

            integralRewardsAndPunishmentsHandler.fansAddBy100(userCacheVo.getUserId());
        }
        return add;
    }

    public Long deleteFollow(Follow entity) {
        Long delete = null;
        delete = stringRedisTemplate.opsForZSet().remove(RedisKeys.ZSET_FOLLOWTO.getValue(entity.getUserId()),
                String.valueOf(entity.getFollowUserId()));
        delete = stringRedisTemplate.opsForZSet().remove(RedisKeys.ZSET_FOLLOWFROM.getValue(entity.getFollowUserId()),
                String.valueOf(entity.getUserId()));


        String key1 = RedisKeys.ZSET_HOST_FOLLOWTO.getValue(entity.getUserId());

        stringRedisTemplate.opsForZSet().remove(key1, String.valueOf(entity.getFollowUserId()));

        String key2 = RedisKeys.ZSET_HOST_FOLLOWFROM.getValue(entity.getFollowUserId());

        stringRedisTemplate.opsForZSet().remove(key2, String.valueOf(entity.getUserId()));

        return delete;
    }

    public Optional<Long> countFollow(long userId, long followUserId) {
        Long rank = stringRedisTemplate.opsForZSet().rank(RedisKeys.ZSET_FOLLOWTO.getValue(userId),
                String.valueOf(followUserId));
        return Optional.ofNullable(rank);
    }

    // 关注我的
    public List<Follow> getFansById(long id, int startNum, int pageSize) {
//		Set<String> userIds = stringRedisTemplate.opsForZSet().reverseRange(RedisKeys.ZSET_FOLLOWFROM.getValue(id),
//				startNum, startNum + pageSize - 1);
//		return userIds.stream().map(s -> Integer.parseInt(s)).collect(toList());
        Set<TypedTuple<String>> followList = stringRedisTemplate.opsForZSet().reverseRangeWithScores(RedisKeys.ZSET_FOLLOWFROM.getValue(id), startNum, startNum + pageSize - 1);
        return followList.stream().map(v -> {
            return new Follow(Long.parseLong(v.getValue()), LocalDateTime.ofInstant(Instant.ofEpochMilli(v.getScore().longValue()), ZoneId.systemDefault()));
        }).collect(Collectors.toList());
    }

    public Set<Long> getFolllowAllByUserId(long id) {
//		Set<String> followSet= new HashSet<>();
        Set<String> followSet = stringRedisTemplate.opsForZSet()
                .reverseRange(RedisKeys.ZSET_FOLLOWTO.getValue(id), 0, -1);
        return followSet.stream().map(Long::parseLong).collect(Collectors.toSet());
    }


    /**
     * 判断主播是否被我关注
     *
     * @param userId     请求用户id
     * @param hostUserId 主播id
     * @return
     */
    public Optional<Long> getMyFollowHostIsExist(long userId, long hostUserId) {
        Long rank = stringRedisTemplate.opsForZSet().rank(RedisKeys.ZSET_HOST_FOLLOWTO.getValue(userId),
                String.valueOf(hostUserId));
        return Optional.ofNullable(rank);
    }

    /**
     * 我关注的主播
     *
     * @param userId
     * @return
     */
    public Set<Long> getMyFollowHost(long userId) {
        String key = RedisKeys.ZSET_HOST_FOLLOWTO.getValue(userId);

        Set<String> followSet = stringRedisTemplate.opsForZSet().reverseRange(key, 0, -1);
        return followSet.stream().map(Long::parseLong).collect(Collectors.toSet());
    }
    /**
     * 主播关注的用户
     *
     * @param userId
     * @return
     */
    public Set<Long> getMyFollowFROMHost(long userId) {
        String key = RedisKeys.ZSET_FOLLOWFROM.getValue(userId);

        Set<String> followSet = stringRedisTemplate.opsForZSet().reverseRange(key, 0, -1);
        return followSet.stream().map(Long::parseLong).collect(Collectors.toSet());
    }
}
